package wayic.utils;

import java.net.URI;
import java.net.URL;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

/**
 * A Parser Utility class
 * 
 * @author Ashesh Nishant
 * 
 */
@SuppressWarnings("unused")
public class CommonUtils {

	private final static Logger LOGGER = LogManager.getLogger(CommonUtils.class);

	private static SimpleDateFormat[] dateFormats = null;

	static {
		final String[] possibleDateFormats = { "EEE, dd MMM yyyy HH:mm:ss z", // RFC_822
				"EEE, dd MMM yyyy HH:mm zzzz", "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:sszzzz",
				"yyyy-MM-dd'T'HH:mm:ss z", "yyyy-MM-dd'T'HH:mm:ssz", // ISO_8601
				"yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HHmmss.SSSz", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd" };

		dateFormats = new SimpleDateFormat[possibleDateFormats.length];
		TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
		for (int i = 0; i < possibleDateFormats.length; i++) {
			dateFormats[i] = new SimpleDateFormat(possibleDateFormats[i], Locale.ENGLISH);
			dateFormats[i].setTimeZone(gmtTZ);
		}

	}

	// Fri, 24 Oct 2002 03:16:15 GMT
	private static SimpleDateFormat dfA = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);

	// 2002-09-19T02:51:16+0200
	private static SimpleDateFormat dfB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

	// 2002-09-19T02:51:16
	private static SimpleDateFormat dfC = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

	// 2002-09-19
	private static SimpleDateFormat dfD = new SimpleDateFormat("yyyy-MM-dd");

	/**
	 * Does the difficult job of figuring out a date value from a String.
	 * 
	 * @param strdate
	 * @return Date
	 */
	public static Date getDate(String strdate) {
		
//		LOGGER.debug("trying to parse :"+strdate);
		Date result = null;
		try{
		strdate = strdate.trim();
		if (strdate.length() > 10) {
			// TODO deal with +4:00 (no zero before hour)
			if ((strdate.substring(strdate.length() - 5).indexOf("+") == 0 || strdate.substring(strdate.length() - 5)
					.indexOf("-") == 0)
					&& strdate.substring(strdate.length() - 5).indexOf(":") == 2) {

				String sign = strdate.substring(strdate.length() - 5, strdate.length() - 4);

				strdate = strdate.substring(0, strdate.length() - 5) + sign + "0"
						+ strdate.substring(strdate.length() - 4);
				// LOGGER.debug("CASE1 : new date " + strdate + " ? "
				// + strdate.substring(0, strdate.length() - 5));

			}
			String dateEnd = strdate.substring(strdate.length() - 6);
			// try to deal with -05:00 or +02:00 at end of date
			// replace with -0500 or +0200
			if ((dateEnd.indexOf("-") == 0 || dateEnd.indexOf("+") == 0) && dateEnd.indexOf(":") == 3) {
				// TODO deal with GMT-00:03
				if ("GMT".equals(strdate.substring(strdate.length() - 9, strdate.length() - 6))) {
//					LOGGER.debug("General time zone with offset, no change ");
				} else {
					// continue treatment
					String oldDate = strdate;
					String newEnd = dateEnd.substring(0, 3) + dateEnd.substring(4);
					strdate = oldDate.substring(0, oldDate.length() - 6) + newEnd;
					// LOGGER.debug("Date from string ->"+strdate);
				}
			}
		}
		int i = 0;
		while (i < dateFormats.length) {
			try {
//				LOGGER.debug("******Parsing  [ "+strdate+" ] with "+dateFormats[i].toPattern());
				result = dateFormats[i].parse(strdate);
				break;
			} catch (java.text.ParseException eA) {
				LOGGER.debug("parsing " + strdate + " [" + dateFormats[i].toPattern()
						+ "] without success, trying again.");
				i++;
			}
		}
		}catch(NumberFormatException nfx){
			LOGGER.warn("While parsing [ "+strdate+" ] NFE : "+nfx);
			nfx.printStackTrace();
			throw nfx;
		}
		return result;
	}
	
	/**
	 * RFC_822 format : "EEE, dd MMM yyyy HH:mm:ss z"
	 * Example: Fri, 24 Oct 2002 03:16:15 GMT
	 *  
	 * @param ms. Milliseconds since January 1, 1970 00:00:00 GMT
	 * @return. Returned date is in GMT.
	 */
	public static String getRFC_822DateAsString(long ms){
		return getRFC_822DateAsString(new Date(ms));
	}
	
	/**
	 * RFC_822 format : "EEE, dd MMM yyyy HH:mm:ss z"
	 * Example: Fri, 24 Oct 2002 03:16:15 GMT
	 * 
	 * @param date
	 * @return. Returned date is in GMT.
	 */
	public static String getRFC_822DateAsString(Date date){
		SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
		df.setTimeZone(TimeZone.getTimeZone("GMT"));
		return df.format(date);
	}

	/**
	 * Utility method to avoid MalformedURLException when creating a URL object
	 * 
	 * @param toURL
	 * @return URL
	 */
	public static URL getURL(String toURL) {
		URL result = null;
		try {
			if ((toURL != null) && (toURL.trim().length() > 0))
				result = new URL(toURL);
		} catch (java.net.MalformedURLException e) {
			LOGGER.warn("Invalid URL " + toURL + " given.");
		}
		return result;
	}
	
	/**
	 * Utility method to avoid MalformedURLException when creating a URL object from URI.
	 * 
	 * @param toURL
	 * @return URL
	 */
	public static URL UriToURL(URI uri) {
		URL result = null;
		try {
			if (uri != null)
				result = uri.toURL();
		} catch (java.net.MalformedURLException e) {
			LOGGER.warn(MessageFormat.format("Cannot convert URI({0}) to URL.",uri));
		}
		return result;
	}
	
	/**
	 * Utility method to return a guess at "Source" given a URL
	 * Delegates to getSource(URL)
	 * @param toURL
	 *            String
	 * @return URL
	 */
	public static String getSource(String urlStr) {
		URL url = getURL(urlStr);
		return getSource(url);
	}
	
	/**
	 * Utility method to return a guess at "Source" given a URL
	 * @param url
	 * @return
	 */
	public static String getSource(URL url) {
		if(url == null){
			return null;
		}
		return url.getHost();
	}

}
